package jch.learn.java.advanced.chapter1_stream.streams;

import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

// 约简操作 | 基本类型流
public class PrimitiveTypeStreams {

    public static void show(String title, IntStream stream){
        final int SIZE = 10;
        int[] firstElements = stream.limit(SIZE + 1).toArray();
        System.out.print(title + ": ");
        for (int i = 0; i < firstElements.length; i++) {
            if (i>0) System.out.print(", ");
            if (i<SIZE) System.out.print(firstElements[i]);
            else System.out.print("...");
        }
        System.out.println();
    }

    public static void main(String[] args) throws URISyntaxException, IOException {
        // 基本类型流

        // java.util.stream.IntStream

        // static IntStream range(int startInclusive,int endExclusive)
        // static IntStream rangeClosed(int startInclusive,int endInclusive)
        // 产生一个由给定范围内的整数构成的IntStream
        // static IntStream of(int... values)
        // 产生一个由给定元素构成的IntStream
        // int[] toArray()
        // 产生一个由当前流中的元素构成的数组
        // int sum()
        // OptionalDouble average()
        // OptionalInt max()
        // OptionalInt min()
        // IntSummaryStatistics summaryStatistics()
        // 产生当前流中元素的总和、平均值、最大值和最小值，或者从中可以获得这些结果的所有四种值的对象
        // Stream<Integer> boxed()
        // 产生用于当前流中的元素的包装器对象流
        IntStream is1 = IntStream.generate(() -> (int) (Math.random() * 100));
        show("is1",is1);
        IntStream is2 = IntStream.range(5,10);
        show("is2",is2);
        IntStream is3 = IntStream.rangeClosed(5,10);
        show("is3",is3);

        // java.util.stream.LongStream

        // static LongStream range(long startInclusive,long endExclusive)
        // static LongStream rangeClosed(long startInclusive,long endExclusive)
        // 用给定范围内的整数产生一个LongStream
        // static LongStream of(long... values)
        // 用给定元素产生一个LongStream
        // long[] toArray()
        // 用当前流中的元素产生一个数组
        // long sum()
        // OptionalDouble average()
        // OptionalLong max()
        // OptionalLong min()
        // LongSummaryStatistics summaryStatistics()
        // 产生当前流中元素的总和、平均值、最大值和最小值，或者从中可以获得这些结果的所有四种值的对象。
        // Stream<Long> boxed()
        // 产生用于当前流中的元素的包装器对象流

        // java.util.stream.DoubleStream

        // static DoubleStream of(double... values)
        // 用给定元素产生一个DoubleStream
        // double[] toArray()
        // 用当前流中的元素产生一个数组
        // double sum()
        // OptionalDouble average()
        // OptionalDouble max()
        // OptionalDouble min()
        // DoubleSummaryStatistics summaryStatistics()
        // 产生当前流中元素的总和、平均值、最大值和最小值，或者从中可以获得这些结果的所有四种值的对象
        // Stream<Double> boxed()
        // 产生用于当前流中的元素的包装器对象流

        Path path = Paths.get(PrimitiveTypeStreams.class.getResource("/gutenberg/alice30.txt").toURI());
        String contents = new String(Files.readAllBytes(path), StandardCharsets.UTF_8);

        Stream<String> words = Stream.of(contents.split("\\PL+"));
        IntStream is4 = words.mapToInt(String::length);
        show("is4",is4);
        String sentence = "\uD835\uDD46 is the set of octonions.";
        System.out.println(sentence);
        // java.lang.CharSequence
        // IntStream codePoints()
        // 产生由当前字符串的所有Unicode码点构成
        IntStream codes = sentence.codePoints();
        System.out.println(codes.mapToObj(c -> String.format("%X",c)).collect(Collectors.joining()));

        Stream<Integer> integers = IntStream.range(0,100).boxed();
        IntStream is5 = integers.mapToInt(Integer::intValue);
        show("is5",is5);

        // java.util.Random

        // IntStream ints()
        // IntStream ints(int randomNumberOrigin,int randomNumberBound)
        // IntStream ints(long streamSize)
        // IntStream ints(long streamSize,int randomNumberOrigin,int randomNumberBound)

        // LongStream longs()
        // LongStream longs(long randomNumberOrigin,long randomNumberBound)
        // LongStream longs(long streamSize)
        // LongStream longs(long streamSize,long randomNumberOrigin,long randomNumberBound)

        // DoubleStream doubles()
        // DoubleStream doubles(double randomNumberOrigin,long randomNumberBound)
        // DoubleStream doubles(long streamSize)
        // DoubleStream doubles(long streamSize,double randomNumberOrigin,double randomNumberBound)

        // 产生随机流。若提供streamSize，则该流就是具有给定数量元素的有限流。当提供了边界时，其元素将位于randomNumberOrigin(包含)和randomNumberBound(不包含)的区间。

        // java.util.Optional(Int|Long|Double)

        // static Optional(Int|Long|Double) of((int|long|double) value)
        // 用所提供的基本类型值产生一个可选对象
        // (int|long|double) getAs(Int|Long|Double)()
        // 产生当前可选对象的值，或者在其为空时抛出一个NoSuchElementException异常
        // (int|long|double) orElse((int|long|double) other)
        // (int|long|double) orElseGet((Int|Long|Double)Supplier other)
        // 产生当前可选对象的值，或者在这个对象为空时产生可替代的值
        // void ifPresent((Int|Long|Double)Consumer consumer)
        // 若当前可选对象不为空，则将其值传递给consumer

        // java.util.(Int|Long|Double)SummaryStatistics

        // long getCount()
        // double getAverage()
        // (int|long|double) getMax()
        // (int|long|double) getMin()
        // 产生收集到的元素的个数、总和、平均值、最大值和最小值

        // 约简操作
        // java.util.Stream

        // Optional<T> reduce(BinaryOperator<T> accumulator)
        // T reduce(T identity,BinaryOperator<T> accumulator)
        // <U> U reduce(U identity,BiFunction<U,? super T,U> accumulator,BinaryOperator<U> combiner)
        // 用给定的accumulator函数产生流中元素的累积总和，若提供了幺元，那么第一个被累计的元素就是该幺元。
        // 若提供了组合器，那么它可以用来将分别累积的各个部分整合成总和。
        // <R> R collect(Supplier<R> supplier,BiConsumer<R,? super T> accumulator,BiConsumer<R,R> combiner)
        // 将元素收集到类型R的结果中。在每个部分上，都会调用supplier来提供初始结果，调用accumulator来交替地将元素添加到结果中，并调用combiner来整合两个结果。
        words = Stream.of(contents.split("\\PL+"));
        int result = words.reduce(0,(total,word) -> total + word.length(), Integer::sum);
        System.out.println("result: " + result);
    }
}
